from chatterbot.storage.storage_adapter import StorageAdapter


class DjangoStorageAdapter(StorageAdapter):
    """
    Storage adapter that allows ChatterBot to interact with
    Django storage backends.
    存储适配器允许聊天机器人互动
    Django存储后端。
    """

    def __init__(self, **kwargs):
        super(DjangoStorageAdapter, self).__init__(**kwargs)

        self.adapter_supports_queries = False
        self.django_app_name = kwargs.get('django_app_name', 'django_chatterbot')

    def count(self):
        from django.apps import apps
        Statement = apps.get_model(self.django_app_name, 'Statement')
        return Statement.objects.count()

    def find(self, statement_text):
        from django.apps import apps
        Statement = apps.get_model(self.django_app_name, 'Statement')
        try:
            return Statement.objects.get(text=statement_text)
        except Statement.DoesNotExist as e:
            self.logger.info(str(e))
            return None

    def filter(self, **kwargs):
        """
        Returns a list of statements in the database
        that match the parameters specified.
        返回数据库中的报表
        匹配指定的参数。
        """
        from django.apps import apps
        Statement = apps.get_model(self.django_app_name, 'Statement')
        from django.db.models import Q

        order = kwargs.pop('order_by', None)

        RESPONSE_CONTAINS = 'in_response_to__contains'

        if RESPONSE_CONTAINS in kwargs:
            value = kwargs[RESPONSE_CONTAINS]
            del kwargs[RESPONSE_CONTAINS]
            kwargs['in_response__response__text'] = value

        kwargs_copy = kwargs.copy()

        for kwarg in kwargs_copy:
            value = kwargs[kwarg]
            del kwargs[kwarg]
            kwarg = kwarg.replace('in_response_to', 'in_response')
            kwargs[kwarg] = value

        if 'in_response' in kwargs:
            responses = kwargs['in_response']
            del kwargs['in_response']

            if responses:
                kwargs['in_response__response__text__in'] = []
                for response in responses:
                    kwargs['in_response__response__text__in'].append(response)
            else:
                kwargs['in_response'] = None

        parameters = {}
        if 'in_response__response__text' in kwargs:
            value = kwargs['in_response__response__text']
            parameters['responses__statement__text'] = value

        statements = Statement.objects.filter(Q(**kwargs) | Q(**parameters))

        if order:
            statements = statements.order_by(order)

        return statements

    def update(self, statement):
        """
        Update the provided statement.
        更新所提供的声明。
        """
        from django.apps import apps
        Statement = apps.get_model(self.django_app_name, 'Statement')

        response_statement_cache = statement.response_statement_cache

        statement, created = Statement.objects.get_or_create(text=statement.text)
        statement.extra_data = getattr(statement, 'extra_data', '')
        statement.save()

        for _response_statement in response_statement_cache:

            response_statement, created = Statement.objects.get_or_create(
                text=_response_statement.text
            )
            response_statement.extra_data = getattr(_response_statement, 'extra_data', '')
            response_statement.save()

            response, created = statement.in_response.get_or_create(
                statement=statement,
                response=response_statement
            )

            if not created:
                response.occurrence += 1
                response.save()

        return statement

    def get_random(self):
        """
        Returns a random statement from the database
        返回从数据库中随机的声明
        """
        from django.apps import apps
        Statement = apps.get_model(self.django_app_name, 'Statement')
        return Statement.objects.order_by('?').first()

    def remove(self, statement_text):
        """
        Removes the statement that matches the input text.
        Removes any responses from statements if the response text matches the
        input text.
        删除匹配的输入文本声明。
        如果响应文本匹配，则从语句中删除任何响应。
        输入文本。
        """
        from django.apps import apps
        from django.db.models import Q

        Statement = apps.get_model(self.django_app_name, 'Statement')
        Response = apps.get_model(self.django_app_name, 'Response')

        statements = Statement.objects.filter(text=statement_text)

        responses = Response.objects.filter(
            Q(statement__text=statement_text) | Q(response__text=statement_text)
        )

        responses.delete()
        statements.delete()

    def drop(self):
        """
        Remove all data from the database.
        从数据库中删除所有数据。
        """
        from django.apps import apps

        Statement = apps.get_model(self.django_app_name, 'Statement')
        Response = apps.get_model(self.django_app_name, 'Response')
        Conversation = apps.get_model(self.django_app_name, 'Conversation')

        Statement.objects.all().delete()
        Response.objects.all().delete()
        Conversation.objects.all().delete()

    def get_response_statements(self):
        """
        Return only statements that are in response to another statement.
        A statement must exist which lists the closest matching statement in the
        in_response_to field. Otherwise, the logic adapter may find a closest
        matching statement that does not have a known response.
        只返回对另一语句的响应语句。
        语句必须存在，它列出最接近的匹配语句
        in_response_to场。否则，逻辑适配器可能会找到一个最近的
        没有已知响应的匹配语句。
        """
        from django.apps import apps
        Statement = apps.get_model(self.django_app_name, 'Statement')
        # print('Statement',Statement)
        Response = apps.get_model(self.django_app_name, 'Response')
        # print('Response',Response)

        responses = Response.objects.all()

        return Statement.objects.filter(in_response__in=responses)

    def get_response_statements_text(self):
        """
        Return only statements that are in response to another statement.
        A statement must exist which lists the closest matching statement in the
        in_response_to field. Otherwise, the logic adapter may find a closest
        matching statement that does not have a known response.
        只返回对另一语句的响应语句。
        语句必须存在，它列出最接近的匹配语句
        in_response_to场。否则，逻辑适配器可能会找到一个最近的
        没有已知响应的匹配语句。
        """
        from django.apps import apps
        Statement = apps.get_model(self.django_app_name, 'Statement')
        Response = apps.get_model(self.django_app_name, 'Response')
        # text = apps.get_model(self.django_app_name, 'text')

        responses = Response.objects.all()

        return Statement.objects.filter(in_response__in=responses)
